(defpackage :argument-submit
  (:use :cl)
  (:nicknames :as)
  (:export :argument-submit-mixin
           :finish-collapsed-argument))

(in-package :argument-submit)

(defclass argument-submit-mixin (p:problem)
  ())

(defgeneric finish-collapsed-argument (problem node)
  (:method-combination progn :most-specific-last))

(defmethod finish-collapsed-argument progn ((problem argument-submit-mixin) node))

(defun do-next-thing (problem node)
  (with-slots (p:transformation p:answers p:diagram h:current) problem
    (let ((correctp (p:correct-input-p problem node)))
      (cond
        ((and (or (p:guidedp problem)
                  (p:input-must-be-correct-p problem))
              (not correctp))
         (p:validate-input-box problem node)
         (exp:lg 'cannot-collapse-node :node (d:id node) :reason :incorrect-answer)
         (cond
           ((p:guidedp problem) (p:show-hint problem))
           ((p:input-must-be-correct-p problem)
             (p:display-message problem :error "~a is the wrong value." (d:quantity node))
            (p:wrong-tile-value problem node)))
         t)
        ((d:find-if-on-tree (lambda (n) (u:neq n node))
                            (d:root p:diagram)
                            :only-type 'd:input-argument)
         (p:validate-input-box problem node)
         (o:collapse-input-argument node)
         (finish-collapsed-argument problem node)
         (setf p:answers (o:generate-answers p:transformation
                                             (d:root p:diagram)))
         (unless (p:suppress-history problem)
           (h:push-item problem h:current))
         (let ((copy (tree:copy-node (d:root p:diagram) t)))
           (d:clear-arrows copy)
           (setf h:current (make-instance 'h:item
                                          :extra p:transformation
                                          :data copy
                                          :correctp correctp)))
         (unless correctp
           (incf (p::fill-mistakes problem)))
         (exp:lg 'collapse-input :correct correctp :new-tree (u:sharp-dot (d:root (p:diagram problem))))
         (p:clear-message problem :all)
         (p::update-guided-state problem :stage)
         (when (p:guidedp problem) (p:show-hint problem))
         t)
        (t
         ;; the regular path should be chosen, so return NIL
         nil)))))

(defmethod p:finish-input-box ((problem argument-submit-mixin) (node d:input-argument))
  (unless (and (d:quantity node)
               (d:valid-input-p node (d:quantity node))
               (do-next-thing problem node))
    (call-next-method)))

(defmethod p:fill-input-box ((problem argument-submit-mixin) (node d:input-argument) value)
  (unless (and value
               (d:valid-input-p node value)
               (setf (d:quantity node) value)
               (do-next-thing problem node))
    (call-next-method)))
